﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web;
using System.Collections;
using Portal.Core.Helper;
using Portal.Data.Entity;
using Portal.Data.Helper;

namespace Portal.Data.Security
{
    public class SecurityProvider
    {
        #region implement singleton pattern

        private static class Singleton
        {
            public static SecurityProvider Instance = new SecurityProvider();
        }

        public static SecurityProvider Instance
        {
            get
            {
                return Singleton.Instance;
            }
        }

        private SecurityProvider()
        {
        }

        #endregion

        #region user

        public bool LogIn(string user, string pwd)
        {
            var u = PortalUser.LogIn(user, pwd);
            if (u == null)
                return false;
            if (!u.Active)
                throw new Exception("Tài khoản của bạn chưa được kích hoạt");
            SetUserCookie(u);
            return true;
        }

        public void LogOut()
        {
            DeleteUserCookie();
        }

        public const string UserCookieName = "Portal@User";
        private const int DateExpired = 7;

        /// <summary>
        /// Store current value
        /// </summary>
        /// <param name="currentUser"></param>
        public void SetUserCookie(PortalUser currentUser)
        {
            //store cookie - store [Id-Password]
            HttpCookie aCookie = HttpContext.Current.Request.Cookies[UserCookieName] ?? new HttpCookie(UserCookieName);

            aCookie.Value = string.Format("{0}-{1}", currentUser.ID, currentUser.Password);

            aCookie.Expires = DateTime.Now.AddDays(DateExpired);
            HttpContext.Current.Response.Cookies.Add(aCookie);

            //store in session - store Object
            HttpContext.Current.Session[UserCookieName] = currentUser;
        }

        public void DeleteUserCookie()
        {
            //remove from session
            HttpContext.Current.Session[UserCookieName] = null;

            //remove cookie
            if (HttpContext.Current.Request.Cookies[UserCookieName] != null)
            {
                //Remove cookie from Server side
                HttpContext.Current.Response.Cookies.Remove(UserCookieName);

                //remove cookie on client
                var aCookie = new HttpCookie(UserCookieName) { Expires = DateTime.Now.AddDays(-DateExpired) };
                HttpContext.Current.Response.Cookies.Add(aCookie);

                aCookie.Value = null;
            }
        }

        #endregion

        #region Misc
        public static bool AllowCall()
        {
            try
            {
                var context = HttpContext.Current;
                string serverLocal = context.Request.Url.Authority;
                string serverRefeffer = "";
                if (context.Request.UrlReferrer != null) serverRefeffer = context.Request.UrlReferrer.Authority;
                return (serverLocal == serverRefeffer);
            }
            catch
            {
                return false;
            }
        }
        /// <summary>
        /// /Files/{0}.txt, {0} datetime: dd_MM_yyyy
        /// </summary>
        private const string VisitPathFormat = "/Files/{0}.txt";
        private const Int32 BufferSize = 128;
        private const string DateFormat = "dd_MM_yyyy";
        private const string KeyVisitByDay = "Visited@Ids@";
        public void IncreaseVisit(int bookId)
        {
            try
            {
                var now = DateTime.Now;
                var key = "B" + bookId;
                //read
                var absPath = string.Format(VisitPathFormat, now.ToString(DateFormat));
                absPath = FileHelper.GetPhysicalPath(absPath);
                string result = "";
                if (File.Exists(absPath))
                {
                    using (var fileStream = File.OpenRead(absPath))
                    {
                        using (var streamReader = new StreamReader(fileStream, Encoding.UTF8, true, BufferSize))
                        {
                            result = streamReader.ReadToEnd();
                        }
                    }
                }
                dynamic json = result.Length > 0
                                   ? DynamicJsonHelper.Parse(result)
                                   : DynamicJsonHelper.Parse("{\"" + key + "\":\"0\"}");

                var val = GetDynamicValue(json, key) ?? "0";
                json[key] = Convert.ToInt32(val) + 1;

                //write new values
                using (var w = new StreamWriter(absPath, false))
                {
                    w.WriteLine(json.ToString());
                }
            }
            catch (Exception ex)
            {
            }
        }

        /// <summary>
        /// Get list Book ID order by Visited desc
        /// like: 1,3,4
        /// </summary>
        /// <returns></returns>
        public string GetHotIdVisited(int max = 0)
        {
            var now = DateTime.Now;
            var key = KeyVisitByDay + now.ToString(DateFormat);
            var obj = CacheHelper.Instance.Get(key);
            if (obj != null)
                return obj.ToString();

            //read file trong 1 tuan, uu tien gan voi ngay hien tai
            var absPath = "";
            for (int i = 0; i < 7; i++)
            {
                var check = string.Format(VisitPathFormat, now.AddDays(-i).ToString(DateFormat));
                check = FileHelper.GetPhysicalPath(check);
                if (File.Exists(check))
                {
                    absPath = check;
                    break;
                }
            }
            if (absPath.Length == 0) return "";

            using (var fileStream = File.OpenRead(absPath))
            {
                using (var streamReader = new StreamReader(fileStream, Encoding.UTF8, true, BufferSize))
                {
                    var result = streamReader.ReadToEnd();
                    var json = DynamicJsonHelper.Parse(result);
                    var list = new List<TempleVisit>();
                    foreach (var item in json)
                    {
                        list.Add(new TempleVisit { Id = Convert.ToInt32(item.Key.Replace("B", "")), Visted = Convert.ToInt32(item.Value) });
                        if (max > 0 && list.Count >= max)
                            break;
                    }
                    //sort and take MAX
                    var arrayIds = list.OrderByDescending(x => x.Visted).Select(x => x.Id).ToList();
                    if (arrayIds.Count > 0)
                    {
                        var ids = string.Join(",", arrayIds);
                        CacheHelper.Instance.Set(key, ids);
                        return ids;
                    }
                }
            }
            return "";
        }
        private string GetDynamicValue(dynamic json, string key)
        {
            try
            {
                return json[key].ToString();
            }
            catch
            {
                return null;
            }
        }
        private class TempleVisit
        {
            public int Id { get; set; }
            public int Visted { get; set; }
        }
        #endregion
    }
}
